//
//  CTVConfigMenuController.m
//  Channltv
//
//  Created by Bruno  Keymolen on 19/07/07.
//  Copyright 2007 channl.tv. All rights reserved.
//

#import "CTVConfigMenuController.h"
#import "CTVConfig.h"
#import "CTVConfigTextEntryController.h"
#import "CTVAutoSync.h"
#import "CTV.h"
#import "CTVChannelCollectionParser.h"
#import "CTVUtil.h"
#import "CTVRateMediaController.h"
#import "CTVAutoUpdate.h"
#import "CTVAutoUpdateController.h"

@implementation CTVConfigMenuController

- (id) initWithScene: (BRRenderScene *) scene{
    if( [super initWithScene: scene] == nil ){
        return ( nil );
	}
	
	m_oldAutoSyncMinutes = [[NSUserDefaults standardUserDefaults]  integerForKey:CTVCONF_AUTOSYNCMIN];
	
	CTVConfigElement* thisElement;
	m_configElements = [[NSMutableArray alloc] init];

	//Username
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Username"];
	[thisElement setConfigID:CTVCONF_USERNAME];
	[thisElement setFunction:@selector(configCTVSelectionUnSyncUserText:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Set your channl.tv login name, this is mandatory for the channel synchronization."];	
	[m_configElements addObject:thisElement];
	
	//Password
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Password"];
	[thisElement setConfigID:CTVCONF_PASSWORD];
	[thisElement setFunction:@selector(configCTVSelectionPasswordText:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Set your channl.tv login password, this is mandatory for the channel synchronization."];		
	[m_configElements addObject:thisElement];
	
	//Download all thumbnails during syncronization
//	thisElement = [[CTVConfigElement alloc] init];
//	[thisElement setMenuName:@"Cache thumbnails during synchronization"];
//	[thisElement setConfigID:CTVCONF_DOWNLOADTHUMBS];
//	[thisElement setFunction:@selector(configCTVSelectionYN:)];
//	[thisElement setIconName:@"settings"];
//	[thisElement setInfo:@"Caching thumbnails will prevent eventually delay's when using the channel and program menu's. Setting this option OFF means that thumbnails need to be loaded from their remote location every time they are showned. The downside is that enabling this option can result in a longer synchronization time."];		
//	[m_configElements addObject:thisElement];

	//Download all clips during syncronization
//	thisElement = [[CTVConfigElement alloc] init];
//	[thisElement setMenuName:@"Cache clips during synchronization"];
//	[thisElement setConfigID:CTVCONF_DOWNLOADCLIPS];
//	[thisElement setFunction:@selector(configCTVSelectionYN:)];
//	[thisElement setIconName:@"settings"];
//	[thisElement setInfo:@"Make a copy of all clips for all channels to the HD when syncronizing."];		
//	[m_configElements addObject:thisElement];

	
	//Make userselection password protected
//	thisElement = [[CTVConfigElement alloc] init];
//	[thisElement setMenuName:@"Make user selection password protected"];
//	[thisElement setConfigID:CTVCONF_PWPROTECTUSERSELECTION];
//	[thisElement setFunction:@selector(configCTVSelectionYN:)];
//	[thisElement setIconName:@"settings"];
//	[thisElement setInfo:@"Protect the selection of your account name on the AplleTV with your channl.tv password."];		
//	[m_configElements addObject:thisElement];
	

	//Clear obsolete clips from cache
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Remove Obsolete Clips"];
	[thisElement setConfigID:CTVCONF_REMOVEOBSOLETECLIPS];
	[thisElement setFunction:@selector(configCTVSelectionYN:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Remove clips from the cache when they are not present in any channel any more."];		
	[m_configElements addObject:thisElement];

	//AutoSync
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Synchronize Interval"];
	[thisElement setConfigID:CTVCONF_AUTOSYNCMIN];
	[thisElement setFunction:@selector(configCTVAutoSync:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Automatically Sync with channl.tv at the configured interval."];		
	[m_configElements addObject:thisElement];


	//Channel view mode
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Channel Mode"];
	[thisElement setConfigID:CTVCONF_CHANNELVIEW];
	[thisElement setFunction:@selector(configCTVSelectionYN:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Channel Mode offers an other experience than traditional clip based viewing. This mode is in Alpha stage. Channel mode is evolving to an experience which will become very close to a 'on demand' replacement of a conventional TV channel experience."];		
	[m_configElements addObject:thisElement];

	//Channel view mode
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Play Intro's"];
	[thisElement setConfigID:CTVCONF_PLAYINTRO];
	[thisElement setFunction:@selector(configCTVSelectionYN:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Play Intro's between clips. This setting only has effect when 'Channel Mode' is on."];		
	[m_configElements addObject:thisElement];



	//Check for Updates
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Check for Updates"];
	[thisElement setConfigID:CTVCONF_CHECKFORUPDATES];
	[thisElement setFunction:@selector(configCTVCheckUpdates:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Check for new channl.tv appliance updates."];		
	[m_configElements addObject:thisElement];

	//Clean cache (not Media)
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"Clean Cache"];
	[thisElement setFunction:@selector(configCTVCleanCache:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"Clean the stack. Erases all cache entries except Media files. Use in case of a corrupt cache."];		
	[m_configElements addObject:thisElement];


	//About
	thisElement = [[CTVConfigElement alloc] init];
	[thisElement setMenuName:@"About"];
	[thisElement setFunction:@selector(showAbout:)];
	[thisElement setIconName:@"settings"];
	[thisElement setInfo:@"About channl.tv"];		
	[thisElement setConfigID:nil];
	[m_configElements addObject:thisElement];
	
	
	//MENU TEST
//	thisElement = [[CTVConfigElement alloc] init];
//	[thisElement setMenuName:@"MenuTest"];
//	[thisElement setFunction:@selector(menuTest:)];
//	[thisElement setIconName:@"settings"];
//	[thisElement setInfo:@"Test Menu."];		
//	[m_configElements addObject:thisElement];
	
	
	[self setListTitle: @"channl.tv Configuration"];	
	[self setPreSelectedIndex];

	 // initialize your resources here
	[[self list] setDatasource: self];

	return self;
		
}



- (void) dealloc
{
	int t;
	for(t=0;t<[m_configElements count];t++){
		[[m_configElements objectAtIndex:t] release];
	}
	[m_configElements release];
    [super dealloc];
}


- (long) itemCount
{
    // return the number of items in your menu list here
	//return ( [menuMainItems count] );
	return ( [m_configElements count] );
}

- (id<BRMenuItemLayer>) itemForRow: (long) row
{
    // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
    // return that object, it will be used to display the list item.
	if ( row >= [m_configElements count] )
		return ( nil );

	id result = [BRTextMenuItemLayer menuItemWithScene: [self scene]];
	
	CTVConfigElement* menuElement = [m_configElements objectAtIndex:row];
	if([menuElement configID] != nil){
		if([menuElement configID] != CTVCONF_AUTOSYNCMIN){
			if([menuElement configID] != CTVCONF_PASSWORD){
				[result setRightJustifiedText:[[NSUserDefaults standardUserDefaults] stringForKey:[menuElement configID]]];
			}else{
				[result setRightJustifiedText:@"*****"];			
			}
		}else{
			int currentMin = [[NSUserDefaults standardUserDefaults]  integerForKey:CTVCONF_AUTOSYNCMIN];
			NSString* displ;
			if(currentMin == 0){
				displ = @"Off";
			}else{
				displ = [CTVUtil getTimeRepresentationString:(currentMin * 60) fullDetail:TRUE fullNames:TRUE];
			}
			[result setRightJustifiedText:displ];
		}
		
		if([menuElement configID] == CTVCONF_CHECKFORUPDATES){
			[result setWaitSpinnerActive:[[CTVAutoUpdate GetInstance] isProcessing]];
		}
	}
	[result setTitle: [menuElement menuName]];
				
	return ( result );
}





- (NSString *) titleForRow: (long) row
{
    if ( row >= [m_configElements count] )
		return ( nil );

	return ( [[m_configElements objectAtIndex: row] menuName] );
}

- (long) rowForTitle: (NSString *) title
{
    long result = -1;
    long i, count = [self itemCount];
    for ( i = 0; i < count; i++ )
    {
        if ( [title isEqualToString: [self titleForRow: i]] )
        {
            result = i;
            break;
        }
    }
    
    return ( result );
}



- (void) itemSelected: (long) row
{
	// This is called when the user presses play/pause on a list item
	CTVConfigElement* menuElement = [m_configElements objectAtIndex:row];

  	//Execute the function
	if([menuElement function] != nil){
		[self performSelector:[menuElement function] withObject:menuElement];
	}
}


- (id<BRMediaPreviewController>) previewControllerForItem: (long) item
{
    // If subclassing BRMediaMenuController, this function is called when the selection cursor
    // passes over an item.
	CTVConfigElement* menuElement = [m_configElements objectAtIndex:item];
		
	BRIconPreviewController* iconPreview = nil;
	NSString* path;

	if ([menuElement iconName] != nil) {
		path = [[NSBundle bundleForClass: [self class]] pathForResource: [menuElement iconName] ofType: @"png"];
	}else{
		path = [[NSBundle bundleForClass: [self class]] pathForResource: @"ApplianceIcon" ofType: @"png"];
	}

	BRBitmapTexture* textureWithImage = [CTVCache createBitmapTextureFromPath:path withScene:[self scene]];
	
		
	if(textureWithImage != nil){
		iconPreview = [[[BRIconPreviewController alloc] initWithScene:[self scene]] autorelease];
		[iconPreview setTexture:textureWithImage]; 

//		[iconPreview setIconHeightFactor:0.90];
		[iconPreview setMessage:[menuElement info]];
//		[iconPreview autorelease];
		
		return ( iconPreview );
	}


    return ( nil );
}


- (void) willBePopped
{
    // The user pressed Menu, but we've not been removed from the screen yet

	//Unsubscribe for sync events
	[[CTVAutoUpdate GetInstance] removeListener:(CTVAutoUpdateListener*)self];
	
	// The user info (username and or password) is changed, we need to re-login
	CTVUser* user = [[CTVConfig GetInstance] activeUser];
	NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
	if([user synchronized] == FALSE){
		[user loginToChannelTVByAlias:[defaults objectForKey:CTVCONF_USERNAME] andPassword:[defaults objectForKey:CTVCONF_PASSWORD]];
	}
	
	//The syncMinutes changed, start the new settings from now
	if(m_oldAutoSyncMinutes != [[NSUserDefaults standardUserDefaults]  integerForKey:CTVCONF_AUTOSYNCMIN]){
		[[CTVAutoSync GetInstance] restart]; 
		
		if([[NSUserDefaults standardUserDefaults]  integerForKey:CTVCONF_AUTOSYNCMIN] > 0){
			[[CTVAutoSync GetInstance] syncNow];
		}
	}


	[super willBePopped];	
}


-(void)configCTVSelectionUnSyncUserText:(CTVConfigElement*)configElement{
	[[[CTVConfig GetInstance] activeUser] setSynchronized:FALSE];
	
	//Show the keyboard
	NSString* title = [NSString stringWithFormat:@"channl.tv %s", [[configElement menuName] UTF8String]];
	id controller = [[CTVConfigTextEntryController alloc] 
					initWithScene: [self scene] 
					andTitle:title  
					andValue:[[NSUserDefaults standardUserDefaults] stringForKey:[configElement configID]] 
					andLabel:[[configElement menuName] lowercaseString] ];
	[controller setConfigKey:[configElement configID]];				
	[controller addObserver:self withSelector:@selector(configCTVTextEditDone:)];
	[[self stack] pushController: controller];	
}


-(void)configCTVSelectionPasswordText:(CTVConfigElement*)configElement{
	[[[CTVConfig GetInstance] activeUser] setSynchronized:FALSE];
	
	//Show the keyboard
	NSString* title = [NSString stringWithFormat:@"channl.tv %s", [[configElement menuName] UTF8String]];
	id controller = [[CTVConfigTextEntryController alloc] 
					initWithScene: [self scene] 
					andTitle:title  
					andValue:[[NSUserDefaults standardUserDefaults] stringForKey:[configElement configID]] 
					andLabel:[[configElement menuName] lowercaseString] ];
	[controller setConfigKey:[configElement configID]];				
	[controller addObserver:self withSelector:@selector(configCTVTextEditDone:)];
	[[self stack] pushController: controller];	
}




-(void)configCTVSelectionYN:(CTVConfigElement*)configElement{
	
	if ( [[[NSUserDefaults standardUserDefaults] stringForKey:[configElement configID]] 
		 isEqualToString:@"Yes"] ){
		 [[NSUserDefaults standardUserDefaults] setObject:@"No" forKey:[configElement configID]];
	}else{
		 [[NSUserDefaults standardUserDefaults] setObject:@"Yes" forKey:[configElement configID]];
	}
	[[NSUserDefaults standardUserDefaults] synchronize];

	//Still did not found a cleaner way to force a redraw of the menuitems
	NSArray* co = [self controls];
	int a;
	for(a=0;a<[co count];a++){
		BRControl* bc = [co objectAtIndex:a];
		[[bc layer] reload]; 
	}
	
	[[self scene] renderScene]; 

}


/* Off - 5 - 15 - 30 - 1 * 60 - 4 * 60 - 12 * 60 - 24 * 60 */
-(void)configCTVAutoSync:(CTVConfigElement*)configElement{
	int choices[] = {0, 1, 5, 15, 30, (1*60), (4*60), (12*60), (24*60), -1};
	int pos;
	int currentMin = [[NSUserDefaults standardUserDefaults]  integerForKey:CTVCONF_AUTOSYNCMIN];
	int newMin = 0;
	
	//Search our value + 1
	pos=0;
	while(choices[pos]>=0){
		if (choices[pos] == currentMin) {
			newMin = choices[pos + 1];
			if(newMin < 0){
				newMin = 0;
			} 
			break;
		}
		pos++;
	}
	
	[[NSUserDefaults standardUserDefaults] setInteger:newMin forKey:CTVCONF_AUTOSYNCMIN];
	[[NSUserDefaults standardUserDefaults] synchronize];

	//Still did not found a cleaner way to force a redraw of the menuitems
	NSArray* co = [self controls];
	int a;
	for(a=0;a<[co count];a++){
		BRControl* bc = [co objectAtIndex:a];
		[[bc layer] reload]; 
	}	
	[[self scene] renderScene]; 

}



-(void)configCTVTextEditDone:(NSNotification*)note{
	CTVConfigTextEntryController* textEntry = [note object];

	if([textEntry textvalue] != nil){
		[[NSUserDefaults standardUserDefaults] setObject:[textEntry textvalue] forKey:[textEntry configKey]];
		[[NSUserDefaults standardUserDefaults] synchronize];
	}
	[[self stack] removeController: textEntry];
	
}


-(void)configCTVCheckUpdates:(CTVConfigElement*)menuelement{
	[[CTVAutoUpdate GetInstance] checkNewVersion];
	//Still did not found a cleaner way to force a redraw of the menuitems
	NSArray* co = [self controls];
	int a;
	for(a=0;a<[co count];a++){
		BRControl* bc = [co objectAtIndex:a];
		[[bc layer] reload]; 
	}
	
	[[self scene] renderScene]; 
	
}


- (void) showAbout:(CTVConfigElement*)menuelement
{
    // 'About' file path
    NSBundle * bundle = [NSBundle bundleForClass: [self class]];
    NSString * path = [bundle pathForResource: @"ctvabout" ofType: @"txt"];
    if ( path == nil )
        return;

    BRDocumentController * result = [[[BRDocumentController alloc]
                                     initWithScene: [self scene]] autorelease];

    // by default uses Unicode (UTF-16), which is what we used when
    // creating the file
    [result setDocumentPath: path encoding:NSASCIIStringEncoding ];


	path = [[NSBundle bundleForClass: [self class]] pathForResource: @"ApplianceIcon" ofType: @"png"];
	BRBitmapTexture* textureWithImage = [CTVCache createBitmapTextureFromPath:path withScene:[self scene]];

 	//[result setHeaderTitle:@"channl.tv"];
    [result setHeaderIcon: textureWithImage /*[self listIcon]*/
         horizontalOffset: [self listIconHorizontalOffset]
            kerningFactor: [self listIconKerningFactor]];

    [result doLayout];


   [[self stack] pushController: result];
}


//Clean cache
-(void)configCTVCleanCache:(CTVConfigElement*)menuelement{

}



- (void) menuTest:(CTVConfigElement*)menuelement{

NSLog(@"menuTest");

	//MENU TEST
	CTVRateMediaController* result = [[[CTVRateMediaController alloc] initWithScene:[self scene]] autorelease];
   [[self stack] pushController: result];

	
}


//Controller will be displayed on screen 
- (void)willBePushed{
	//Subscribe for sync events (menu updates)
	[[CTVAutoUpdate GetInstance] addListener:(CTVAutoUpdateListener*)self];

	[super willBePushed];
}






//AutoUpdateListener
-(void)autoUpdateCheckFail{

	//Still did not found a cleaner way to force a redraw of the menuitems
	NSArray* co = [self controls];
	int a;
	for(a=0;a<[co count];a++){
		BRControl* bc = [co objectAtIndex:a];
		[[bc layer] reload]; 
	}
	
	[[self scene] renderScene]; 
}

-(void)autoUpdateCheckDone:(NSString*)version{
	
	//Still did not found a cleaner way to force a redraw of the menuitems
	NSArray* co = [self controls];
	int a;
	for(a=0;a<[co count];a++){
		BRControl* bc = [co objectAtIndex:a];
		[[bc layer] reload]; 
	}
	
	[[self scene] renderScene]; 

	//Do we have a new update ?
	if([[CTVAutoUpdate GetInstance] updateAvailable]){
		//Only if this screen is not already on
		id activeController = [[self stack] peekController];
		if([activeController isKindOfClass:[CTVAutoUpdateController class]]){
			NSLog(@"Update is already on screen");
		}else{
			NSLog(@"New Update  screen");
			CTVAutoUpdateController* controller = [[[CTVAutoUpdateController alloc] initWithScene:[self scene]] autorelease];
			[[self stack] pushController: controller];
		}
	}

}




//Easter Egg
- (BOOL)brEventAction:(BREvent*)event{
	BOOL ret;
	
//	NSLog(@"Event %d", [event remoteAction]);

	ret = [super brEventAction:event];
	
	if([event remoteAction] == kBRRemoteActionRewind){
		if([event value] == 0){
			if(m_er1 == FALSE){
				m_el1 = TRUE;
				m_er1 = FALSE;
				m_el2 = FALSE;
			}else if(m_el1 == TRUE && m_er1 == TRUE){
				NSLog(@"Easter egg");
				ret = YES;
				m_el1 = FALSE;
				m_er1 = FALSE;
				m_el2 = FALSE;
			}else{
				m_el1 = FALSE;
				m_er1 = FALSE;
				m_el2 = FALSE;
			}	
		}
	}else if([event remoteAction] == kBRRemoteActionFastForward){
		if([event value] == 0){
			if(m_el1 == TRUE){
				m_er1 = TRUE;
			}else{
				m_el1 = FALSE;
				m_er1 = FALSE;
				m_el2 = FALSE;	
			}
		}
	}else{
		m_el1 = FALSE;
		m_er1 = FALSE;
		m_el2 = FALSE;	
	}
	
	

	return ret;
}

@end
